<!--
 * @Author: Li Zengkun
 * @Date: 2022-09-05 20:13:59
 * @LastEditors: Li Zengkun
 * @LastEditTime: 2022-09-07 16:24:18
 * @Description: 
-->
<template>
  <div>
    <a-breadcrumb>
      <a-breadcrumb-item v-for="item in article.breadcrumb" :key="item">{{item}}</a-breadcrumb-item>
    </a-breadcrumb>
    <div class="article-content">
      <h1>{{article.title}}</h1>
      <UserCard />
      <article v-html="article.content1"></article>
      <h3>定义真实 DOM</h3>
      <pre><code class='language-HTML line-numbers'>{{article.code1}}</code></pre>
      <h3>实例化 vue</h3>
      <pre><code class='language-javascript line-numbers'>{{article.code2}}</code></pre>
      <h3>观察 render 的 render，我们能得到虚拟DOM</h3>
      <pre><code class='language-javascript line-numbers'>{{article.code3}}</code></pre>
      <article v-html="article.content2"></article>

    </div>
  </div>
</template>

<script setup>
import { ref, reactive,onMounted } from "vue";
import UserCard from "@/components/UserCard.vue"
import Prism from "prismjs";

onMounted(() => {
  Prism.highlightAll();
});

const article = {
  breadcrumb:['底层原理','虚拟DOM'],
  title:'虚拟DOM',
  content1:`<h2>一、什么是虚拟DOM</h2><p style="text-align: start;">虚拟 DOM （<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>Virtual DOM</code></span> ）这个概念相信大家都不陌生，从 <span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>React</code></span> 到 <span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>Vue</code></span> ，虚拟 <span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span> 为这两个框架都带来了跨平台的能力（<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>React-Native</code></span> 和 <span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>Weex</code></span>）</p><p style="text-align: start;">实际上它只是一层对真实<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>的抽象，以<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>JavaScript</code></span> 对象 (<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>VNode</code></span> 节点) 作为基础的树，用对象的属性来描述节点，最终可以通过一系列操作使这棵树映射到真实环境上</p><p style="text-align: start;">在<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>Javascript</code></span>对象中，虚拟<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span> 表现为一个 <span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>Object</code></span>对象。并且最少包含标签名 (<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>tag</code></span>)、属性 (<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>attrs</code></span>) 和子元素对象 (<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>children</code></span>) 三个属性，不同框架对这三个属性的名命可能会有差别</p><p style="text-align: start;">创建虚拟<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>就是为了更好将虚拟的节点渲染到页面视图中，所以虚拟<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>对象的节点与真实<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>的属性一一照应</p><p style="text-align: start;">在<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>vue</code></span>中同样使用到了虚拟<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>技术</p>`,
  code1:`<div id="app">
    <p class="p">节点内容</p>
    <h3>{{ foo }}</h3>
</div>`,
code2:`const app = new Vue({
    el:"#app",
    data:{
        foo:"foo"
    }
})`,
code3:`(function anonymous(
) {
	with(this){return _c('div',{attrs:{"id":"app"}},[_c('p',{staticClass:"p"},
					  [_v("节点内容")]),_v(" "),_c('h3',[_v(_s(foo))])])}})`,
content2:`<p style="text-align: start;"><span style="color: rgb(44, 62, 80); background-color: rgb(255, 255, 255); font-size: 16px;">通过</span>VNode<span style="color: rgb(44, 62, 80); background-color: rgb(255, 255, 255); font-size: 16px;">，</span>vue<span style="color: rgb(44, 62, 80); background-color: rgb(255, 255, 255); font-size: 16px;">可以对这颗抽象树进行创建节点,删除节点以及修改节点的操作， 经过</span>diff<span style="color: rgb(44, 62, 80); background-color: rgb(255, 255, 255); font-size: 16px;">算法得出一些需要修改的最小单位,再更新视图，减少了</span>dom<span style="color: rgb(44, 62, 80); background-color: rgb(255, 255, 255); font-size: 16px;">操作，提高了性能</span></p><h2 style="text-align: start;">二、为什么需要虚拟DOM</h2><p style="text-align: start;"><span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>是很慢的，其元素非常庞大，页面的性能问题，大部分都是由<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>操作引起的</p><p style="text-align: start;">真实的<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>节点，哪怕一个最简单的<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>div</code></span>也包含着很多属性。</p><p style="text-align: start;"><img src="https://static.vue-js.com/cc95c7f0-442c-11eb-ab90-d9ae814b240d.png" alt="真实DOM节点的属性" data-href="https://static.vue-js.com/cc95c7f0-442c-11eb-ab90-d9ae814b240d.png" style=""></p><p style="text-align: start;"><span style="color: rgb(44, 62, 80); background-color: rgb(255, 255, 255); font-size: 16px;">操作</span>DOM<span style="color: rgb(44, 62, 80); background-color: rgb(255, 255, 255); font-size: 16px;">的代价仍旧是昂贵的，频繁操作还是会出现页面卡顿，影响用户的体验</span></p><p style="text-align: start;"><strong>举个例子：</strong></p><p style="text-align: start;">你用传统的原生<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>api</code></span>或<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>jQuery</code></span>去操作<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>时，浏览器会从构建<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>树开始从头到尾执行一遍流程</p><p style="text-align: start;">当你在一次操作时，需要更新10个<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>节点，浏览器没这么智能，收到第一个更新<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>请求后，并不知道后续还有9次更新操作，因此会马上执行流程，最终执行10次流程</p><p style="text-align: start;">而通过<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>VNode</code></span>，同样更新10个<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>节点，虚拟<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>不会立即操作<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>，而是将这10次更新的<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>diff</code></span>内容保存到本地的一个<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>js</code></span>对象中，最终将这个<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>js</code></span>对象一次性<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>attach</code></span>到<span style="color: rgb(71, 101, 130); background-color: rgba(27, 31, 35, 0.05);"><code>DOM</code></span>树上，避免大量的无谓计算</p><p style="text-align: start;"><span style="font-size: 16px;">很多人认为虚拟 DOM 最大的优势是 diff 算法，减少 JavaScript 操作真实 DOM 的带来的性能消耗。虽然这一个虚拟 DOM 带来的一个优势，但并不是全部。虚拟 DOM 最大的优势在于抽象了原本的渲染过程，实现了跨平台的能力，而不仅仅局限于浏览器的 DOM，可以是安卓和 IOS 的原生组件，可以是近期很火热的小程序，也可以是各种GUI</span></p>`,
}
</script>

<style lang="less" scoped>
</style>
